package com.atguigu.gulimall.member.service.impl;

import com.atguigu.common.to.member.SocialUserTo;
import com.atguigu.common.to.member.WeiBoUserInfoTo;
import com.atguigu.gulimall.member.dao.MemberLevelDao;
import com.atguigu.gulimall.member.entity.MemberLevelEntity;
import com.atguigu.gulimall.member.exception.PhoneExistException;
import com.atguigu.gulimall.member.exception.UserNameExistException;
import com.atguigu.gulimall.member.vo.UserLoginVo;
import com.atguigu.gulimall.member.vo.UserRegisterVo;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.http.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.member.dao.MemberDao;
import com.atguigu.gulimall.member.entity.MemberEntity;
import com.atguigu.gulimall.member.service.MemberService;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;


@Service("memberService")
@Slf4j
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Resource
    private MemberLevelDao memberLevelDao;

    @Resource
    private RestTemplate restTemplate;

    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void register(UserRegisterVo vo) {
        MemberEntity memberEntity = new MemberEntity();
        // 设置默认等级
        MemberLevelEntity memberLevelEntity = memberLevelDao.getDefaultStatusId();
        memberEntity.setLevelId(memberLevelEntity.getId());

        // 检查用户名和密码
        boolean phoneIsUnique = checkPhoneIsUnique(vo.getPhone());
        boolean userNameIsUnique = checkUserNameIsUnique(vo.getUserName());

        memberEntity.setUsername(vo.getUserName());
        memberEntity.setMobile(vo.getPhone());

        // 设置密码
        String password = passwordEncoder.encode(vo.getPassword());
        memberEntity.setPassword(password);

        if (!phoneIsUnique && !userNameIsUnique) {
            log.info("手机号与用户名校验通过，即将插入数据 {}", memberEntity);
            baseMapper.insert(memberEntity);
        }

    }

    @Override
    public boolean checkPhoneIsUnique(String phone) throws PhoneExistException {
        Integer count = baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("mobile", phone));
        if (count > 0) {
            throw new PhoneExistException();
        }
        return false;
    }

    @Override
    public boolean checkUserNameIsUnique(String userName) throws UserNameExistException {
        Integer count = baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("username", userName));
        if (count > 0) {
            throw new UserNameExistException();
        }
        return false;
    }

    @Override
    public MemberEntity login(UserLoginVo vo) {
        String acctNo = vo.getAcctNo();
        MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("username", acctNo).or().eq("mobile", acctNo));
        if (memberEntity != null) {
            boolean matches = passwordEncoder.matches(vo.getPassword(), memberEntity.getPassword());
            if (matches) {
                return memberEntity;
            }
        }
        return null;
    }

    @Override
    public MemberEntity oauth2WebiBoLogin(SocialUserTo to) {
        String uid = to.getUid();
        // 根据 uid 查询用户
        MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));
        if (memberEntity != null) {
            // 表示不是首次登录了,需要更新token信息
            MemberEntity member = new MemberEntity();
            member.setId(memberEntity.getId());
            member.setAccessToken(to.getAccess_token());
            member.setExpiresIn(to.getExpires_in());
            member.setSocialUid(uid);
            this.baseMapper.updateById(member);

            memberEntity.setAccessToken(to.getAccess_token());
            memberEntity.setExpiresIn(to.getExpires_in());
            memberEntity.setSocialUid(uid);
            return memberEntity;
        } else {
            // 新建用户
            MemberEntity member = new MemberEntity();
            member.setAccessToken(to.getAccess_token());
            member.setExpiresIn(to.getExpires_in());
            member.setSocialUid(uid);

            // 根据token获取第三方信息
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
            requestBody.add("access_token", to.getAccess_token());
            requestBody.add("uid", to.getUid());
            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);

            ResponseEntity<WeiBoUserInfoTo> response = restTemplate.exchange(
                    "https://api.weibo.com/2/users/show.json", HttpMethod.GET, requestEntity, WeiBoUserInfoTo.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                WeiBoUserInfoTo vo = response.getBody();
                log.info("response is {}", vo);

                // 设置用户信息
                member.setUsername(vo.getName());
                member.setGender("m".equals(vo.getGender()) ? 1 : 0);
                // 设置其他信息
            }

            // 保存数据
            this.baseMapper.insert(member);

            return member;
        }
    }

    @Override
    public MemberEntity oauth2Login(AuthUser to) {
        String uid = to.getSource() + "_" + to.getUuid();
        // 根据 uid 查询用户
        MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));
        if (memberEntity != null) {
            // 表示不是首次登录了,需要更新token信息
            MemberEntity member = new MemberEntity();
            member.setId(memberEntity.getId());
            member.setAccessToken(to.getToken().getAccessToken());
            member.setExpiresIn(to.getToken().getExpireIn());
            member.setSocialUid(uid);
            this.baseMapper.updateById(member);

            memberEntity.setAccessToken(to.getToken().getAccessToken());
            memberEntity.setExpiresIn(to.getToken().getExpireIn());
            memberEntity.setSocialUid(uid);
            return memberEntity;
        } else {
            // 新建用户
            MemberEntity member = new MemberEntity();
            member.setAccessToken(to.getToken().getAccessToken());
            member.setExpiresIn(to.getToken().getExpireIn());
            member.setSocialUid(uid);

            // 设置用户信息
            member.setUsername(to.getNickname());
            member.setGender(Integer.parseInt(to.getGender().getCode()));
            // 设置其他信息
            member.setNickname(to.getNickname());
            member.setEmail(to.getEmail());
            member.setHeader(to.getAvatar());
            member.setSign(to.getRemark());
            member.setStatus(1);
            member.setCreateTime(new Date());

            // 保存数据
            this.baseMapper.insert(member);

            return member;
        }
    }

}